//https://uniapp.dcloud.net.cn/api/a-d/rewarded-video

const ADType = {
	RewardedVideo: "RewardedVideo",
	Interstitial: "Interstitial",
	FullScreenVideo: "FullScreenVideo"
}

class AdHelper {

	constructor() {
		this._ads = {}
	}

	load(options, onload, onerror) {
		let ops = this._fixOldOptions(options)
		let {
			adpid
		} = ops

		if (!adpid || this.isBusy(adpid)) {
			uni.showToast({
				title: "正在加载广告，请稍后再试",
				icon: "none"
			})
			return
		}

		this.get(ops).load(onload, onerror)
		console.log("预加载广告完成")
	}

	show(options, onsuccess, onfail) {
		let ops = this._fixOldOptions(options)
		let {
			adpid
		} = ops

		if (!adpid) {
			return
		}

		uni.showLoading({
			mask: true
		})

		var ad = this.get(ops)

		ad.load(() => {
			uni.hideLoading()
			ad.show((e) => {
				onsuccess && onsuccess(e)
			})
		}, (err) => {
			uni.hideLoading()
			onfail && onfail(err)
		})
	}

	isBusy(adpid) {
		return (this._ads[adpid] && this._ads[adpid].isLoading)
	}

	get(options) {
		const {
			adpid
		} = options
		if (!this._ads[adpid]) {
			this._ads[adpid] = this._createAdInstance(options)
		}

		return this._ads[adpid]
	}

	_createAdInstance(options) {
		const adType = options.adType || ADType.RewardedVideo
		delete options.adType

		let ad = null;
		if (adType === ADType.RewardedVideo) {
			ad = new RewardedVideo(options)
		} else if (adType === ADType.FullScreenVideo) {
			ad = new FullScreenVideo(options)
		} else if (adType === ADType.Interstitial) {
			ad = new Interstitial(options)
		}

		return ad
	}

	_fixOldOptions(options) {
		return (typeof options === "string") ? {
			adpid: options
		} : options
	}
}

const EXPIRED_TIME = 1000 * 60 * 30
const ProviderType = {
	CSJ: 'csj',
	GDT: 'gdt'
}

const RETRY_COUNT = 1

class AdBase {
	constructor(adInstance, options = {}) {
		this._isLoad = false
		this._isLoading = false
		this._lastLoadTime = 0
		this._lastError = null
		this._retryCount = 0

		this._loadCallback = null
		this._closeCallback = null
		this._errorCallback = null

		const ad = this._ad = adInstance
		ad.onLoad((e) => {
			this._isLoading = false
			this._isLoad = true
			this._lastLoadTime = Date.now()

			this.onLoad()
		})
		ad.onClose((e) => {
			this._isLoad = false
			this.onClose(e)
		})
		/* ad.onVerify((e) => {
			// e.isValid
		}) */
		ad.onError(({
			code,
			message
		}) => {
			this._isLoading = false
			const data = {
				code: code,
				errMsg: message
			}

			if (code === -5008) {
				this._loadAd()
				return
			}

			if (this._retryCount < RETRY_COUNT) {
				this._retryCount += 1
				this._loadAd()
				return
			}

			this._lastError = data
			this.onError(data)
		})
	}

	get isExpired() {
		return (this._lastLoadTime !== 0 && (Math.abs(Date.now() - this._lastLoadTime) > EXPIRED_TIME))
	}

	get isLoading() {
		return this._isLoading
	}

	getProvider() {
		return this._ad.getProvider()
	}

	load(onload, onerror) {
		this._loadCallback = onload
		this._errorCallback = onerror

		if (this._isLoading) {
			return
		}

		if (this._isLoad) {
			this.onLoad()
			return
		}

		this._retryCount = 0

		this._loadAd()
	}

	show(onclose) {
		this._closeCallback = onclose

		if (this._isLoading || !this._isLoad) {
			return
		}

		if (this._lastError !== null) {
			this.onError(this._lastError)
			return
		}

		const provider = this.getProvider()
		if (provider === ProviderType.CSJ && this.isExpired) {
			this._loadAd()
			return
		}

		this._ad.show()
	}

	onLoad(e) {
		if (this._loadCallback != null) {
			this._loadCallback()
		}
	}

	onClose(e) {
		if (this._closeCallback != null) {
			this._closeCallback({
				isEnded: e.isEnded
			})
		}
	}

	onError(e) {
		if (this._errorCallback != null) {
			this._errorCallback(e)
		}
	}

	destroy() {
		this._ad.destroy()
	}

	_loadAd() {
		this._isLoad = false
		this._isLoading = true
		this._lastError = null
		this._ad.load()
	}
}

class RewardedVideo extends AdBase {
	constructor(options = {}) {
		super(plus.ad.createRewardedVideoAd(options), options)
	}
}

class FullScreenVideo extends AdBase {
	constructor(options = {}) {
		super(plus.ad.createFullScreenVideoAd(options), options)
	}
}
class Interstitial extends AdBase {
	constructor(options = {}) {
		super(plus.ad.createInterstitialAd(options), options)
	}
}

export default new AdHelper()
